home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
CHAINDOC.ZIP
/
CHAIN4.DOC
next >
Wrap
Text File
|
1995-06-17
|
25KB
|
566 lines
╒═══════════════════════════════════════════════════════════════╗
│■ ■ ║
│ ║
│ █████████░ ██░ ║
│ ██░ ██░ ██░ ██░ ██████░ ██░ ████████░ ██░ ██░ ║
│ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ║
│ ██░ ██░ ██░ ██░ ██░ ██░ ████████░ ██░ ██░ ║
│ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ║
│ █████████░ ████████░ ██░ ██████░ ██░ ██░ ███░ ███░ ║
│ ║
│ T ∙ R ∙ I ∙ A ∙ D ║
│■ ■ ║
└───────────────────────────────────────────────────────────────╜
╔══════════════╗
║ ∙ PRESENTS ∙ ║
╚══════════════╝
Chain-4 Documentary Version 2.0
───────────────────────────────────────────────────────────────────────────────
Written By : Vulture Total Files : 2
File Type : Textfile Release Date : 17th of June 1995
Difficulty : Medium level Filename : CHAINDOC.ZIP
───────────────────────────────────────────────────────────────────────────────
Note: This is version 2.0. It includes some pascal procedures at the end of
the document.
I started writing this little document as a helpfile for myself coz I think
a great way to learn is writing things down. I found myself having troubles
understanding the assembler code found in various trainers so I thought it
was a good idea to make a textfile wich covered some of the main tricks there
are concerning chain-4 code. Worked out great! Infact, I think this file can
be of great help to all starting gfxcoders out there, so I have decided to
release it into the public domain. There are already lots of docs available
on the subject but there's always room for one more, eh? :)
Hmm, I will assume you know a little about VGA programming and assembler code.
If you don't know anything about it yet, this doc might be a little hard to
understand. If you are already a chain-4 guru, you can go back to sleep coz
this is probably too easy for you. This document describes the very basics of
chain-4. But anyway, enough of thiz cr*p. . . on with the real stuff :)
=-=-=-=-=-=-=-=-=-=-=-=-= CHAIN-4 VIDEOMODE DOCFILE =-=-=-=-=-=-=-=-=-=-=-=-=-
=-= What is chain-4 ? =-=
Most VGA intros are written in mode 13h. This is 320*200*256 mode. The memory
in this mode is lineair and thus fairly easy to handle. The resolution isn't
that great but for most intros it's enough. One can make very cewl graphics
in this mode. So all in all this is a great mode to use. However, a major
disadvantage is the fact that only 64 kB of VGA memory can be accessed.
This is the entire screen (320*200 = almost 64kB = 1 page) you see in front
of you. So, when you use this mode you aren't using the full standard 256kB
of memory present on the VGA-card but just 64kB. For most people mode 13h is
sufficient but for the more serious coders it just isn't enough. They want to
use the full 256 kB of memory available for e.g fast pageflipping, full screen
scrolling and lots of other cewl things. Here we go:
Chain-4 is a method of accessing 256 kB of memory on a standard VGA-card.
When using chain-4 the VGA memory is unchained wich bassicly means that the
memory is no longer lineair as were the case in standard mode 13h. Due to VGA
hardware this gives us 256 kB of memory. On a chain-4 screen pixels are placed
on so-called bitplanes. Normally there are four pages (=planes) available,
each 64kB big. This is coz a segment can only be 64 kB big. And 4*64kB=256kB.
It is also possible to 'tweak' the videomode and get into higher resolutions.
E.g 320*240*256. This results in you having less pages available because
you have more pixels on a page. However, in this doc I will not go into
tweaking the videomode but stay with the basics.
Take a look at the following diagram. It shows a possible chain-4 screen.
0 X 640
┌──────────────────────┐
│ =>┌────────┐ │
│ │ View │ │ The viewport always shows 1/4=64k of the
│ │ Port │ │ total chain-4 screen. In this case the
│ │ │ │ chain-4 screen is 2 pages width and 2
Y │ └────────┘ │ pages high. The total chain-4 screen can
│ │ be anything that adds up to 4 pages.
│ Chain-4 screen │ More of this l8r downbelow.
│ │
└──────────────────────┘
400
The memory layout of the chain-4 screen is rather different from the normal
MCGA gfxmode. Like I said previously, the memory is divided into 4 bitplanes.
Each 64 kB big because of segmentlimitations. The following picture should
clear some things. Suppose you are plotting pixels with colors 0 to 9.
If the color has reached value 9, it's set to 0 again. Take a look:
The standard lineair MCGA mode gives us:
┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
│00│01│02│03│04│05│06│07│08│09│00│01│...etc...
In unchained VGA memory, the screen will be represented as follows:
Plane 0:
Address: 0 10 70 79 (Not 319 anymore)
┌──────────────────────────────────────┐
│0482604826048260 ..... 0482604826│
│ │
Plane 1:
Address: 0 10 70 79
┌──────────────────────────────────────┐
│1593715937159371 ..... 1593715937│
│ │
Plane 2:
Address: 0 10 70 79
┌──────────────────────────────────────┐
│2604826048260482 ..... 2604826048│
│ │
Plane 3:
Address: 0 10 70 79
┌──────────────────────────────────────┐
│3715937159371593 ..... 3715937159│
│ │
This means that when you point to an address, you are actually pointing to
the addresses of FOUR neighbouring pixels. To be more exact: address 0
points to pixels 0,1,2 and 3, each on different planes. Adress 1 points to
pixels 4,5,6 and 7, etcetera. Now, before writing the pixel, you will have to
enable the plane of the pixel you want. If pixel P is in plane I, pixel P+1
will be in plane (I+1)%4. The screenwidth is now set to 80 instead of 320.
This should make perfect sence. Think about it. One adress points to 4 pixels.
Multiply 80 by 4 and you'll get your basic 320 again. And there are still 320
pixels across visible. 200 pixels in height remains the same. Simple!
So, that's a bit different, eh? Also more difficult to code. But don't let it
scare you. The advantages you gain from using this mode are well worth the
effort. And besides, you have this doc so it's not that hard anymore :)
This document explains how to access the unchained videomode, enable
planes for writing and reading, moving across the screens and putting
pixels on the screens.
A. How to access the unchained VGA mode.
B. How to activate the plane we want to write to.
C. How to activate the plane we want to read from.
D. How to move across the various planes (screens).
E. How to place a pixel on the chain-4 screen.
F. Various pascal procedures concerning this code.
G. Closing words.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
A. HOW TO ACCESS THE UNCHAINED VGA MODE.
This is done by setting various vga registers. The code below is very
basic and can be expanded but it's suitable for our needs right now.
1. Get into MCGA mode.
Done by a simple bios-call.
mov ax,0013h ; Videomode 13h 320*200*256
int 10h ; Set the mode
2. Unchain VGA-mode.
This is done by turning the 3rd bit in index 4 of the sequencer off.
mov dx,03c4h ; Sequencer Address Register
mov al,4 ; Index 4 - Memory mode
out dx,al ; Select it
inc dx ; 03c5h - Here we set the mem mode.
in al,dx ; Get settings inside register
and al,11110111b ; Disable 3rd bit will give us chain-4
or al,00000100b ; Bit 2 enabled => no odd/even-scheme
out dx,al ; Inform VGA
3. Turn off doubleword mode by setting the Underline Location register
Use CRT controllers port 3d4h index 14h
mov dx,3d4h
mov al,14h ; Select index 14 "Underline Location Register"
out dx,al
inc dx
in al,dx
and al,10111111b ; Bit 6 := 0 => Disable double word adressing
out dx,al
4. Turn off word adressing by setting the Mode Control register.
Now use CRT controllers port 3d4h index 17h
mov dx,3d4h
mov al,17h ; Mode Control Register
out dx,al
inc dx
in al,dx ; Get what's in the register
or al,01000000b ; Bit 6 := 1
out dx,al ; Thus disabling wordmode
5. Set the logical screen width.
To do this, use the CRT controllers port 3d4h index 13h.
mov dx,3d4h ; Select the port
mov al,13h ; Select index Logical Screen Width
out dx,al ; Inform VGA about it
inc dx ; Increase port value
mov al,[Size] ; Set the size
out dx,al ; Give info to VGA
Like I stated previously, the chain-4 screen can be any size that adds
up to 4 screens with a screen being 320*200 pixels large (=64kB).
Size * 8 is how many pixels across there are on the chain-4 screen.
Examine this:
Size = 40 => 320 pixels across = 1 screen across, 4 screens down
Size = 80 => 640 pixels across = 2 screens across, 2 screens down
Size = 160 => 1280 pixels across = 4 screens across, 1 screen down
These are all possibilities. Remember, only 320 pixels across are visible.
We need to know the size of the screen for almost all dealings with the
chain-4 screen so it's clever to put the size in a constant. Just like I did
in the example code.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
B. HOW TO ACTIVATE THE PLANE WE WANT TO WRITE TO.
Before we can plot a pixel on the chain-4 screen, we have to select and
activate the plane we want to write to. You must alter the 4 least signifi-
cant bits (bits 0,1,2 and/or 3) in index 2 (set/reset enable register) of
the graphics controller. This is done as follows:
1. Select gfx controller: port 3ceh
mov dx,3ceh
2. Select index 2 => Set/reset enable register
mov al,02
3. Pass info to VGA
out dx,al
4. Increase port value
inc dx
5. Select plane for writing ; 1 = on 0 = off
mov al,00000001b ; enables plane 0 (byte=76543210)
6. Give info to VGA
out dx,al
So, to enable plane 0 for writing:
mov dx,3ceh ; Select port
mov al,02 ; Select index
out dx,al ; Give info to VGA
inc dx ; Increase port value (datafield)
mov al,00000001b ; Enable plane 0 (bit 0 is now set)
out dx,al ; Inform VGA 'bout thiz
For all other planes the same code can be used. Just change the MOV command.
You can also use the AND command for this purpose. Play with it and learn.
All 4 planes can be set for writing to so you can set 4 pixels at the same
time with just 1 movsb. Simply enable the 4 least significant bits at once.
Wow! This is fast... :)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
C. HOW TO ACTIVATE THE PLANE WE WANT TO READ FROM.
Same goes for reading. First activate the plane and then read the pixel.
Do it like thiz:
1. Select gfx controller port 3ceh
mov dx,3ceh
2. Select index
mov al,04 ; Read plane index
3. Inform VGA about this
out dx,al
4. Increase port value
inc dx
5. Select plane for reading
mov al,00000000b ; Select plane 0 for reading
6. Inform VGA
out dx,al
Bits 0 and 1 must be altered to select a plane for reading. (byte=76543210)
00: plane 0 read enable.
01: plane 1 read enable.
10: plane 2 read enable.
11: plane 3 read enable.
As you might have guessed, you cannot read from all planes at the same time.
So, to enable plane 0 for reading, you'd do the following:
mov dx,3ceh ; Select port
mov al,04 ; Select index
out dx,al ; Give info to VGA
inc dx ; Increase port value
mov al,00000000b ; Enable plane 0 (since all bits are zero)
out dx,al ; Inform VGA
That's it. Easy enough, eh? :)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
D. HOW TO MOVE ACROSS THE VARIOUS PLANES (=screens).
We move across the screens by changing the upperleft adress of the viewport.
┌─────────────────────────────────────┐
│ =>┌────────┐ │
│ │ View │ Chain-4 │ The viewport always shows 1/4 of the
│ │ Port │ Screen │ total Chain-4 screen.
│ │ │ │
│ └────────┘ │
└─────────────────────────────────────┘
This is of course an excellent way to scroll. Having a big picture on two or
more screens and then moving the viewport over the screens is much faster than
trying to scroll the screen in plain MCGA mode. Just takes a view port-writes.
To do this trick, we have to use the Crt controller port 03d4h. We need index
0Ch and 0Dh. That's Start Adress High and Start Adress Low.
1. Select Crt port
mov dx,03d4h
2. Select index 0Ch
mov al,0Ch ; Start adress High
3. Inform VGA
out dx,al
4. Increase port-value
inc dx ; Data register
5. Move high byte into al
mov al,bh ; Assuming bx contains total adress
6. Change VGA settings
out dx,al
Now we have set the high byte of the total adress. Only thing left to do is
set the low byte too. This is done the similar way except we use index 0Dh.
1. Select Crt port
mov dx,03d4h
2. Select index 0Dh
mov al,0Dh ; Start adress Low
3. Inform VGA
out dx,al
4. Increase port-value
inc dx
5. Move low byte into al
mov al,bl ; Assuming bx contains total adress
6. Change VGA settings
out dx,al
Now we have set the total new adress of the viewport and have moved the
entire viewport across the entire chain-4 screen. E.g you can go into a loop
where you let a picture bounce on the bottom of the screen by changing the
startingadress of the viewport. That would be pretty cewl, eh? :)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
E. HOW TO PLACE PIXELS ON THE CHAIN-4 SCREEN.
Ofcourse we want to plot pixels on the screen. But since we are dealing with
various planes, this is not so simple as on a MCGA screen. We have to know
on wich plane we want to plot the pixel and howfar into the plane we must be.
To find the plane we wish to plot on, we do this calculation (x mod 4), and
the x-coordinate on that plane is found by (x div 4). We work out our y by
multiplying it by the size of our chain-4 screen. This all might sound a bit
strange. Why not make a small program to see what I mean? Anyway, in steps:
1. Multiply Y by our screensize (40,80 or 160)
y*size
2. Find out hofar in the plane we must be
x div 4
3. Finalize location
y:=y+x
4. Find out on wich plane to plot
x mod 4
5. Set that plane
6. Plot the pixel
And now for the assember code:
mov ax,[Y] ; Put Y in ax
xor bx,bx ; Reset bx to zero
mov bl,[Size] ; Size in bl (it's a byte!)
imul bx ; Now ax:=ax*bx => Y:=Y*Size
shl ax,1 ; Multiply by 2 => Y:=Y*2 (Dunno why)
mov bx,ax ; Save Y-value in bx
mov ax,[X] ; Move X-value into ax
mov cx,ax ; And in cx
shr ax,2 ; Divide ax by 4 (x div 4)
add bx,ax ; Y:=Y+X bx contains final location
and cx,00000011b ; cl:=0,1,2 or 3 (x mod 4)
mov ah,00000001b ; Start value = plane 0
shl ah,cl ; E.g plane 2: 00000001 => 00000100
mov dx,3c4h ; Sequencer Register
mov al,2 ; Select index 2 => plane enable
out dx,ax ; Enable selected plane
mov ax,0a000h ; VGA segment
mov es,ax ; es points to VGA
mov al,[col] ; Color in al
mov es:[bx], al ; Place it
This is a complete chain-4 putpixel procedure. You can ofcourse make a pascal
procedure out of it. Look at the next chapter for that one. The procedure can
ofcourse be optimized but then... what can't :)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
F. VARIOUS PASCAL PROCEDURES CONVERNING THIS CODE.
I have included some pascal procedures for you to examine/use. The code works
just fine and you should not have any troubles implementing this in your own
programs.
Procedure SetChain4; Assembler; { Get into Chain-4 videomode }
Asm
mov ax,0013h { Videomode 13h 320*200*256 }
int 10h { Set the mode }
mov dx,03c4h { Sequencer Address Register }
mov al,4 { Index 4 - Memory mode }
out dx,al { Select it }
inc dx { 03c5h - Here we set the mem mode }
in al,dx { Get settings inside register }
and al,11110111b { Disable 3rd bit will give us chain4 }
or al,00000100b { Bit 2 enabled => no odd/even-scheme }
out dx,al { Inform VGA }
mov dx,3d4h
mov al,14h { Turn off Double Word mode }
out dx,al
inc dx
in al,dx
and al,10111111b { Bit 6 := 0 => Disable double word adressing }
out dx,al
mov dx,3d4h
mov al,17h { Mode Control Register }
out dx,al
inc dx
in al,dx { Get what's in the register }
or al,01000000b { Bit 6 := 1 => Address memory as lineair array }
out dx,al
mov dx,3d4h { Select the port }
mov al,13h { Select the index Logical Screen Width }
out dx,al { Inform VGA about it }
inc dx { Increase port value }
mov al,[Size] { Set the size }
out dx,al { Give info to VGA }
End;
Procedure Cls_C4; Assembler;
Asm
mov dx,03c4h { Select port 03c4h }
mov al,2 { Map Mask Register }
out dx,al
inc dx
mov al,00001111b { Select all planes for writing }
out dx,al { So we can clear all planes at once }
mov ax,0a000h
mov es,ax
xor di,di { Set es:di = Screen Mem }
mov ax,0 { Color to put = black }
mov cx,32768 { 32768 (words) * 2 = 65536 bytes = 1 screen }
cld
rep stosw { Clear it }
End;
Procedure SetPixelC4(X,Y:Integer; Color:Byte); Assembler;
Asm
mov ax,[Y] { Put Y in ax }
xor bx,bx { Reset bx to zero }
mov bl,[Size] { Size in bl (it's a Byte!) }
imul bx { Now ax:=ax*bx => Y:=Y*Size }
shl ax,1 { Multiply by 2 => Y:=Y*2 (Dunno why) }
mov bx,ax { Save Y-value in bx }
mov ax,[X] { Move X-value into ax }
mov cx,ax { And in cx }
shr ax,2 { Divide ax by 4 (x div 4) }
add bx,ax { Y:=Y+X bx contains final location }
and cx,00000011b { cl:=0,1,2 or 3 (x mod 4) }
mov ah,00000001b { Start value (plane 0) }
shl ah,cl { Eg plane 2: 00000001 => 00000100 }
mov dx,3c4h { Sequencer Register }
mov al,2 { Select index 2 => plane enable }
out dx,ax { Enable selected plane }
mov ax,0a000h { VGA segment }
mov es,ax { es points to VGA }
mov al,[Color] { Color in al }
mov es:[bx], al { Place it }
End;
Procedure MoveTo(X,Y : Integer); Assembler;
Asm
mov ax,[Y] { Y value }
xor bx,bx { Reset bx to zero }
mov bl,[Size] { Size in bl }
shl bx,1 { *2 (dunno why) }
imul bx { Multiply Y with size }
mov bx,ax { Save Y into BX }
add bx,[X] { Y:=Y+X }
mov dx,03d4h { CRTC address register }
mov al,0ch { Start Address High register }
out dx,al
inc dx
mov al,bh { Send high byte of start address }
out dx,al
dec dx
mov al,0dh { Start Address Low register }
out dx,al
inc dx
mov al,bl { Send low byte of start address }
out dx,al
End;
That's it. It should be easy enough to make a small sample-program with these
procedures. Why don't you try to scroll a fullscreen picture with this...
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
G. CLOSING WORDS
Thanx must go to Denthor & Eze of Aphyxia and Robert Smith for providing info
on the topic. If you haven't got their documents, I suggest you get them.
They are quite good and can be found on various FTP-sites and BBSses.
Hmm, well, the following cr*p is supposed to be stated so here we go:
I (Vulture) take no responsibility for any mistakes found in this document.
So use at your own risk. I have used this code myself and did not have any
problems with it so this code should not give ya a hard time.
Wanna contact Outlaw for some reason? Then call one of the Outlaw distros
and leave a message.
If U actually use this info, a greet to all people stated above would be
appreciated. A little graditude doesn't hurt, does it? :)
One thing left to say. Be carefull doing this kinda stuff when you are a
beginner. Just take it one step at the time. (I did)
Signed: Vulture / Outlaw Triad / Cri
─────────────────────────┬───────────────────────┬────────────────────────────
Outlaw Triad Distros : │ Greetz from Outlaw: │ Releases sofar:
─────────────────────────┼───────────────────────┼────────────────────────────
│ │
■ Blue Thunder ■ │ - DemoLisher │ ■ MESSAGE (dosscroller)
■ +31 (0)36-5346967 ■ │ - ThunderHawk │
│ - Ash │ ■ VGA-VUL1 (sources)
│ - The Machine │
■ FireHouse ■ │ - X∙N∙TRiC │ ■ CHAINDOC (textfile)
■ +31 (0)58-2661590 ■ │ - Utter Chaos │
│ - Crusher │ ■ VGA-VUL2 (sources)
│ │
│ - Critical │ ■ BASICDOC (textfile)
Open for more! │ - Da Frisian Force │
│ - Tribal │ + various bbs-intros
│ │
─────────────────────────┴───────────────────────┴────────────────────────────
■ (C) 1995 O∙U∙T∙L∙A∙W T∙R∙I∙A∙D ■
──────────────────────────────────────────────────────────────────────────────